package demo4;

import java.io.*;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;

public class RequestHandler implements Runnable {
    private final Socket clientSocket;
    private final String webRoot;

    public RequestHandler(Socket socket, String webRoot) {
        this.clientSocket = socket;
        this.webRoot = webRoot;
    }

    @Override
    public void run() {
        BufferedReader in = null;
        OutputStream out = null;

        try {
            in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
            out = clientSocket.getOutputStream();

            // 读取请求行
            String requestLine = in.readLine();
            if (requestLine == null) return;
            System.out.println("=== HTTP请求信息 ===");
            System.out.println("请求行：" + requestLine);

            String[] parts = requestLine.split(" ");
            if (parts.length < 3) {
                sendError(out, 400, "错误请求");
                return;
            }
            String method = parts[0].toUpperCase();
            String url = parts[1];
            String httpVersion = parts[2];
            System.out.println("HTTP版本：" + httpVersion);
            System.out.println("请求方法：" + method);
            System.out.println("请求URL：" + url);

            // 读取请求头
            System.out.println("=== 请求头信息 ===");
            String header;
            while ((header = in.readLine()) != null && !header.isEmpty()) {
                System.out.println("请求头：" + header);
            }

            // 处理请求方法
            switch (method) {
                case "GET":
                    handleGet(out, url); // 调用handleGet处理
                    break;
                case "POST":
                    handlePost(out, in);
                    break;
                default:
                    sendError(out, 501, "未实现");
            }

        } catch (FileNotFoundException e) {
            try {
                sendError(out, 404, "文件未找到");
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            // 关闭资源（注意：fileIn在handleGet内部关闭，这里不需要处理）
            try {
                if (in != null) in.close();
                if (out != null) out.close();
                if (clientSocket != null) clientSocket.close();
                System.out.println("=== 连接已关闭 ===\n");
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    // 处理GET请求（核心修改：在方法内部声明fileIn）
    private void handleGet(OutputStream out, String url) throws IOException {
        System.out.println("\n=== 处理GET请求 ===");
        if (url.equals("/")) {
            url = "/index.html";
        }
        System.out.println("处理URL：" + url);

        // 规范化URL路径，防止目录遍历攻击
        if (url.contains("..")) {
            sendError(out, 403, "禁止访问");
            return;
        }

        File file = new File(webRoot, url);
        System.out.println("文件路径：" + file.getAbsolutePath());

        // 检查文件是否存在且是文件（不是目录）
        if (!file.exists() || !file.isFile()) {
            System.out.println("文件不存在或不是文件");
            sendError(out, 404, "文件未找到");
            return;
        }

        System.out.println("文件存在，大小：" + file.length() + " 字节");

        // 构建响应头
        StringBuilder responseHeader = new StringBuilder();
        responseHeader.append("HTTP/1.1 200 OK\r\n");
        SimpleDateFormat dateFormat = new SimpleDateFormat(
                "EEE, dd MMM yyyy HH:mm:ss zzz", Locale.US);
        dateFormat.setTimeZone(TimeZone.getTimeZone("GMT"));
        String dateStr = dateFormat.format(new Date());
        responseHeader.append("Date: ").append(dateStr).append("\r\n");
        responseHeader.append("Server: MyJavaServer/1.0\r\n");
        responseHeader.append("Content-Length: ").append(file.length()).append("\r\n");
        responseHeader.append("Content-Type: ").append(getContentType(file.getName())).append("\r\n");
        responseHeader.append("Last-Modified: ").append(dateFormat.format(new Date(file.lastModified()))).append("\r\n");
        responseHeader.append("\r\n");

        System.out.println("=== 响应信息 ===");
        System.out.println("响应状态：HTTP/1.1 200 OK");
        System.out.println("响应头：\n" + responseHeader.toString().replace("\r\n", "\n"));

        out.write(responseHeader.toString().getBytes());

        FileInputStream fileInput = new FileInputStream(file);
        byte[] buffer = new byte[1024];
        int len;
        int totalBytes = 0;
        while ((len = fileInput.read(buffer)) != -1) {
            out.write(buffer, 0, len);
            totalBytes += len;
        }
        out.flush();
        fileInput.close();
        System.out.println("实际发送字节数：" + totalBytes);
    }

    // 处理POST请求
    private void handlePost(OutputStream out, BufferedReader in) throws IOException {
        StringBuilder postData = new StringBuilder();
        String line;
        while ((line = in.readLine()) != null) {
            postData.append(line);
        }
        System.out.println("POST请求体：" + postData.toString());

        String responseBody = "POST请求已接收，数据长度：" + postData.length();
        byte[] responseBodyBytes = responseBody.getBytes("UTF-8");

        String response = "HTTP/1.1 200 OK\r\n"
                + "Content-Type: text/plain; charset=UTF-8\r\n"
                + "Content-Length: " + responseBodyBytes.length + "\r\n"
                + "\r\n"
                + responseBody;

        out.write(response.getBytes(StandardCharsets.UTF_8));
        out.flush();
    }

    // 发送错误响应（不变）
    private void sendError(OutputStream out, int code, String msg) throws IOException {
        System.out.println("发送错误响应：" + code + " " + msg);
        byte[] bodyBytes = msg.getBytes(StandardCharsets.UTF_8);

        String response = "HTTP/1.1 " + code + " " + msg + "\r\n"
                + "Content-Type: text/plain; charset=UTF-8\r\n"
                + "Content-Length: " + bodyBytes.length + "\r\n"
                + "\r\n"
                + msg;

        out.write(response.getBytes(StandardCharsets.UTF_8));
        out.flush();
    }

    // 获取Content-Type
    private String getContentType(String fileName) {
        if (fileName.endsWith(".html") || fileName.endsWith(".htm")) {
            return "text/html; charset=UTF-8";
        } else if (fileName.endsWith(".css")) {
            return "text/css; charset=UTF-8";
        } else if (fileName.endsWith(".js")) {
            return "application/javascript; charset=UTF-8";
        } else if (fileName.endsWith(".jpg") || fileName.endsWith(".jpeg")) {
            return "image/jpeg";
        } else if (fileName.endsWith(".png")) {
            return "image/png";
        } else if (fileName.endsWith(".txt")) {
            return "text/plain; charset=UTF-8";
        } else {
            return "application/octet-stream";
        }
    }
}